#ifndef SYMBOLS_HEAD
#define SYMBOLS_HEAD
#include <map>
#include <string>
#include <algorithm>
#include "lexer.hpp"
#include "inter.hpp"

using std::swap;
using std::string;
using std::map;
/*
Symbols类实现符号表和类型
*/

class Env{          //这里是一个链表，我头开始痛了
public:
    Env(Env&& n){
        swap(table,n.table);
        swap(prev,n.prev);
    }
    Env(Env& n){
        prev = &n;
    }

    void put(Token w,Id i){
        table[w]=i;
    }
    Id get(Token w){
        for(Env*e =this;e!=nullptr;e=e->prev){
            if(e->table.count(w))return (e->table)[w];
        }
        throw(string("Find Error! In the file symbols.hpp")+"Env::get : "+"There is not key "+ w.toString());
    }

protected:
    Env*prev;

private:
    map<Token,Id>table;
};
Type max(Type p1,Type p2){//用自动类型转化时判断计算类型
    if(!p1.numeric()||!p2.numeric())throw("file : symbols. In function max, line : 43");
    else if(p1 == Type::Float||p2==Type::Float)return Type::Float;
    else if(p1 == Type::Int||p2==Type::Int)return Type::Int;
    else return Type::Char;
}

class Type:public Word{
public:
    int width;
    Type(string s="",int tag=0,int w=0):Word(s,tag),width(w){}
    static const Type Int,Float,Char,Bool,Operator;

    bool numeric(){//检查一个类型是否是数字，此语言只允许数字进行类型转换
        return (*this==Type::Int)||(*this==Type::Float)||(*this==Type::Char);
    }   
    bool operator==(Type p){
        return (width == p.width)&&(p.lexme()==lexme())&&(p.tag()==tag());
    }
    friend Type max(Type ,Type);
private:
};
const Type Type::Int("int",Tag::BASIC,4),
Type::Float("float",Tag::BASIC,8),
Type::Char("char",Tag::BASIC,1),
Type::Bool("bool",Tag::BASIC,1),
Type::Operator("operator",Tag::BASIC,1);


class Array:public Type{
public:
    Type of;
    int size;
    Array(int sz,Type p):Type("[]",Tag::INDEX,sz*(p.width)),of(p),size(sz){}
    string toString(){
        return string("[")+std::to_string(size)+"]"+ of.toString();
    }
};

#endif